import Db from "../utils/db";
import GameMgr_xlch from "./gamemgr_xlch";
import GameMgr_xzdd from "./gamemgr_xzdd";



const callPath = 'game_server->roommgr.ts->'
/**本服务器创建的游戏房间的数量 */
let totalRooms = 0;
const DI_FEN = [1, 2, 5];
const MAX_FEN = [3, 4, 5];
const JU_SHU = [4, 8];
const JU_SHU_COST = [2, 3];
const rooms: rooms = {};
const creatingRooms = {};
const userLocation: { [key: string]: seat } = {};

function logErr(funName) {
    let pathFun = 'game_server->roommgr.ts->';
    return (errMsg) => {
        console.log(pathFun + funName + '()->错误信息:' + errMsg);
    };
}

export default class Roommgr{
    /**返回存在的房间的数量 */
    static getTotalRooms(){
        return totalRooms;
    }

    /**
     * 创建房间
     * @param creator 创建者的ID
     * @param roomConf 玩法选项信息
     * @param gems 宝石数量
     * @param ip 
     * @param port 
     */
    static async createRoom(creator, roomConf: conf, gems, ip, port): Promise<{errcode?: number, errmsg?: string, roomId?}>{
        if(
            roomConf.type == null ||
            roomConf.diFen == null ||
            roomConf.ziMo == null ||
            roomConf.jiangDui == null ||
            roomConf.huanSanZhang == null ||
            roomConf.zuiDaFanShu == null ||
            roomConf.juShuXuanZe == null ||
            roomConf.dianGangHua == null ||
            roomConf.menQing == null ||
            roomConf.tianDiHu == null
        ){
            return {errcode: 1, errmsg: callPath + 'createRoom->玩法的选项不能为空'};
        }

        if(roomConf.diFen < 0 || roomConf.diFen > DI_FEN.length){
            return {errcode: 2, errmsg: callPath + 'createRoom->底分选择不对'};
        }

        if(roomConf.ziMo < 0 || roomConf.ziMo > 2){
            return {errcode: 3, errmsg: callPath + 'createRoom->自摸选择不对'};
        }

        if (roomConf.zuiDaFanShu < 0 || roomConf.zuiDaFanShu > MAX_FEN.length){
            return {errcode: 4, errmsg: callPath + 'createRoom->最大番数选择不对'};
        }

        if(roomConf.juShuXuanZe < 0 || roomConf.juShuXuanZe > JU_SHU.length){
            return {errcode: 5, errmsg: callPath + 'createRoom->局数选择不对'};
        }

        const cost = JU_SHU_COST[roomConf.juShuXuanZe];
        if(cost > gems){
            return { errcode: 2222, errmsg: callPath + 'createRoom->gems不够开房的，请充值！' };
        }

        let roomId = generateroomId();
        creatingRooms[roomId] = true;
        const roomIsExist = await Db.is_room_exist(roomId);
        if(roomIsExist){
            delete creatingRooms[roomId];
            roomId = generateroomId();
            creatingRooms[roomId] = true;
        }
        // 初始化数据
        const createTime = Math.ceil(Date.now() / 1000);
        const roomInfo: roomInfo= {
            uuid: '',
            id: roomId,
            numOfGames: 0,
            createTime: createTime,
            nextButton: 0,
            seats: [],
            conf: {
                type: roomConf.type,
                baseScore: DI_FEN[roomConf.diFen],
                ziMo: roomConf.ziMo,
                jiangDui: roomConf.jiangDui,
                hsz: roomConf.huanSanZhang,
                dianGangHua: roomConf.dianGangHua,
                menQing: roomConf.menQing,
                tianDiHu: roomConf.tianDiHu,
                maxFan: MAX_FEN[roomConf.zuiDaFanShu],
                maxGames: JU_SHU[roomConf.juShuXuanZe],
                creator: creator,
            }
        };
        roomInfo.gameMgr = roomConf.type == 'xlch' ? GameMgr_xlch : GameMgr_xzdd;
        for(let i = 0; i < 4; i++){
            roomInfo.seats.push({
                userId: 0,
                score: 0,
                name: '',
                ready: false,
                seatIndex: i,
                numZiMo: 0,
                numJiePao: 0,
                numDianPao: 0,
                numAnGang: 0,
                numMingGang: 0,
                numChaJiao: 0,
            });
        }

        // 写入数据库
        const conf = roomInfo.conf;
        const uuid = await Db.create_room(roomInfo.id, roomInfo.conf, ip, port, createTime);
        delete createTime[roomId];
        if(uuid){
            roomInfo.uuid = uuid;
            rooms[roomId] = roomInfo;
            totalRooms++;
            return {errcode: 0, roomId: roomId};
        }
        else{
            return {errcode: 6, errmsg: callPath + 'create_room-> Db.create_room创建房间时写入数据出错'};
        }
    }


    /**
     * 进入房间
     */
    static async enterRoom(roomId, userId, userName){
        let room = rooms[roomId];
        if(!room){
            const dataArr = await Db.get_room_data(roomId);
            if(dataArr == null){
                return {
                    errcode: 12,
                    errmsg: callPath + 'enterRoom()->错误信息：查询t_rooms时没有数据或查询出错！',
                };
            }

            room = this.constructRoomFromDb(dataArr);
        }

        const flagNum = await this._enterRoom(room, roomId, userId, userName);
        let errmsg = '';
        switch(flagNum){
            case 0:
                break;
            case 13:
                errmsg = '房间已满'
                break;
            case 15:
                errmsg = '更新数据失败';
                break;
        }
        return {
            errcode: flagNum,
            errmsg: callPath + 'enterRoom()->错误信息：' + errmsg,
        };
    }


    static async _enterRoom(room: roomInfo, roomId, userId, userName){
        if(this.getUserRoom(userId) == roomId){
            return 0;
        }

        for(let i = 0; i < 4; i++){
            let seat = room.seats[i];
            if(seat.userId <= 0){
                seat.userId = userId;
                seat.name = userName;
                userLocation[userId] = {
                    roomId: roomId,
                    seatIndex: i,
                };
                const flag = await Db.update_seat_info(roomId, i, seat.userId, '', seat.name);
                if(flag){
                    return 0;
                }
                else{
                    return 15;
                }
            }
        }

        // 房间已满
        return 13;
    }


    /**
     * 生成座位信息
     */
    static constructRoomFromDb(dataArr: t_rooms){
        const roomInfo: roomInfo = {
            uuid: dataArr.uuid,
            id: dataArr.id,
            numOfGames: dataArr.num_of_turns,
            createTime: dataArr.create_time,
            nextButton: dataArr.next_button,
            seats: [],
            conf: JSON.parse(dataArr.base_info),
        };
        roomInfo.gameMgr = roomInfo.conf.type == 'xlch' ? GameMgr_xlch : GameMgr_xzdd;
        const roomId = roomInfo.id;
        for(let i = 0; i < 4; i++){
            let s:seat = roomInfo.seats[i] = {};
            s.userId = dataArr['user_id' + i];
            s.score = dataArr['user_score' + i];
            s.name = dataArr['user_name' + i];
            s.ready = false;
            s.seatIndex = i;
            s.numZiMo = 0;
            s.numJiePao = 0;
            s.numDianPao = 0;
            s.numAnGang = 0;
            s.numMingGang = 0;
            s.numChaJiao = 0;
            if(s.userId > 0){
                userLocation[s.userId] = {
                    roomId: roomId,
                    seatIndex: i,
                };
            }

        }
        rooms[roomId] = roomInfo,
        totalRooms++;
        return roomInfo;
    }


    /**
     * 根据用户ID获取用户房间号
     * @param userId 
     */
    static getUserRoom(userId){
        const location = userLocation[userId];
        if(location != null){
            return location.roomId;
        }
    }

    /**
     * 根据房间ID获取此房间的玩法信息
     */
    static getRoomInfo(roomId){
        return rooms[roomId];
    }

    /**根据用户ID获取座位编号 */
    static getUserSeat(userId){
        const location = userLocation[userId];
        if(location != null){
            return location.seatIndex;
        }
    }

    /**将用户状态设为准备 */
    static setReady(userId, ready){
        const log = logErr('setReady');

        const roomId = this.getUserRoom(userId);
        if(roomId == null){
            log('roomId == null');
            return;
        }

        const roomInfo = this.getRoomInfo(roomId);
        if (roomInfo == null) {
            log('roomInfo == null');
            return;
        }

        const seatIndex = this.getUserSeat(userId);
        if (seatIndex == null) {
            log('seatIndex == null');
            return;
        }

        const s = roomInfo.seats[seatIndex];
        s.ready = ready;
    }


    /**
     * 销毁房间
     * @param roomId 
     */
    static async destroy(roomId){
        const log = logErr('distroy');

        const roomInfo = rooms[roomId];
        if(roomInfo == null){
            log('roomInfo == null');
            return;
        }

        for(let i = 0; i < 4; i++){
            const userId = roomInfo.seats[i].userId;
            if(userId > 0){
                delete userLocation[userId];
                await Db.set_room_id_of_user(userId, null);
            }
        }

        delete rooms[roomId];
        totalRooms--;
        Db.delete_room(roomId);
    }


    static isCreator(roomId, userId){
        const roomInfo = rooms[roomId];
        if(roomInfo == null){
            return false;
        }
        return roomInfo.conf.creator == userId;
    }


    static exitRoom(userId){
        const log = logErr('exitRoom');

        const location = userLocation[userId];
        if(location == null){
            log('location == null');
            return;
        }

        const roomId = location.roomId;
        const seatIndex = location.seatIndex;
        const room = rooms[roomId];
        delete userLocation[userId];
        if(room == null || seatIndex == null){
            log('room == null || seatIndex == null');
            return;
        }

        const seat = room.seats[seatIndex];
        seat.userId = 0;
        seat.name = '';

        let numOfPlayers = 0;
        room.seats.forEach((s) => {
            if(s.userId >0){
                numOfPlayers++;
            }
        });

        Db.set_room_id_of_user(userId, null);
        if(numOfPlayers == 0){
            this.destroy(roomId);
        }
    }
}




/**随机生成6位数的房间ID*/
function generateroomId(){
    let roomId = '';
    for(let i = 0; i < 6; i++){
        roomId += Math.floor(Math.random() * 10);
    }

    if(rooms[roomId] || creatingRooms[roomId]){
        generateroomId();
    }
    else{
        return roomId;
    }
}